package org.e_gold.dao.impl;

import java.util.Date;
import java.util.List;

import org.e_gold.dao.GenericDAO;
import org.e_gold.model.ValueObject;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Example;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

public abstract class AbstractGenericDAO<T extends ValueObject> implements GenericDAO<T> {

	private Class<T> type;

	@Autowired
	private SessionFactory sessionFactory;

	protected Session getCurrentSession() {

		return sessionFactory.getCurrentSession();
	}

	public AbstractGenericDAO(Class<T> type) {

		this.type = type;
	}

	@Override
	@Transactional
	public T insert(T t) {

		t.setInsertTimeStamp(new Date());
		t.setModifyTimeStamp(new Date());
		getCurrentSession().save(t);
		return t;
	}

	@Override
	@Transactional
	public void delete(T t) {

		getCurrentSession().delete(t);
	}

	@Override
	@Transactional
	public T update(T t) {

		t.setModifyTimeStamp(new Date());
		getCurrentSession().update(t);
		return t;
	}

	@Override
	@Transactional
	public List<T> update(List<T> lst){

		for(T t : lst){
			t.setModifyTimeStamp(new Date());
			getCurrentSession().update(t);
		}

		return lst;
	}

	@SuppressWarnings("unchecked")
	@Override
	@Transactional
	public T findOne(Long id) {

		return (T) getCurrentSession().get(type, id);
	}

	@SuppressWarnings("unchecked")
	@Override
	@Transactional
	public List<T> findAll() {

		Criteria criteria = getCurrentSession().createCriteria(type);
		return criteria.list();
	}

	@SuppressWarnings("unchecked")
	@Transactional
	@Override
	public List<T> findByPropertyName(String propName, Object value){
		try{
			Criteria crit = getCurrentSession().createCriteria(type);
			crit.add(Restrictions.like(propName, value));
			return crit.list();

		}catch(Exception ex){
			ex.printStackTrace();
		}
		return null;
	}

	@SuppressWarnings("unchecked")
	@Transactional
	@Override
	public T getUniqueByPropertyName(String propName, Object value) {
		try{
			Criteria crit = getCurrentSession().createCriteria(type);
			crit.add(Restrictions.eq(propName, value.toString()));
			return (T) crit.uniqueResult();

		}catch(Exception ex){
			ex.printStackTrace();
		}
		return null;
	}

	@SuppressWarnings("unchecked")
	@Transactional
	@Override
	public List<T> findByExample(T exampleInstance, String... excludeProperty) {
		try{
			Criteria crit = getCurrentSession().createCriteria(type);
			Example ex = Example.create(exampleInstance);
			for(String s : excludeProperty){
				ex.excludeProperty(s);
			}
			crit.add(ex);
			return crit.list();
		}catch(Exception ex){
			ex.printStackTrace();
		}
		return null;
	}

}
